
#include "Spark/Net/TcpServer.h"
#include "Spark/Net/EventLoop.h"
#include "Spark/Net/SocketAddr.h"
#include "Spark/Utils/Logger.h"

#include <utility>

#include <stdio.h>
#include <unistd.h>

using namespace std::placeholders;

int numThreads = 0;

class EchoServer
{
  public:
    EchoServer(EventLoop* loop, const SocketAddr& listenAddr)
        : loop_(loop), server_(loop, listenAddr, "EchoServer")
    {
        server_.setConnectionCallback(
            [this](const TcpConnectionPtr& conn){ onConnection(conn); });
        server_.setRecvMessageCallback(
            [this](const TcpConnectionPtr& conn, MsgBuffer* buffer, TimePoint tp){
                onMessage(conn, buffer, tp);
            });
        server_.setIoLoopNum(numThreads);
    }

    void start()
    {
        server_.start();
    }
    // void stop();

  private:
    void onConnection(const TcpConnectionPtr& conn)
    {
        LOG_TRACE << conn->peerAddr().toStringPort() << " -> "
                  << conn->localAddr().toStringPort() << " is "
                  << (conn->connected() ? "UP" : "DOWN");
        LOG_INFO << conn->getTcpInfoString();
        if (conn->connected())
            conn->send("hello\n");
    }

    void onMessage(const TcpConnectionPtr& conn, MsgBuffer* buf, TimePoint time)
    {
        std::string msg(buf->retrieveAllAsString());
        LOG_TRACE << conn->name() << " recv " << msg.size();
        conn->send(msg);
    }

    EventLoop* loop_;
    TcpServer server_;
};

int main(int argc, char* argv[])
{
    LOG_INFO << "pid = " << getpid();
    LOG_INFO << "sizeof TcpConnection = " << sizeof(TcpConnection);
    if (argc > 1)
    {
        numThreads = atoi(argv[1]);
    }
    bool ipv6 = argc > 2;
    EventLoop loop;
    SocketAddr listenAddr("0.0.0.0", 2000);
    EchoServer server(&loop, listenAddr);

    server.start();

    loop.loop();
}
